﻿/// <reference path="../../jquery.d.ts"/>
/// <reference path="../../jquerymobile.d.ts"/>
/// <reference path="../../google.maps.d.ts" />
/// <reference path="../../CoordinateConverter/Geo.CoordinateConverter.ts" />

module Geo.CoordinateConverter {
    export class CoordinateConverterViewModel {
        private _coordinateInputElement: HTMLInputElement;
        private _gpsOutputElement: HTMLHeadingElement;
        private _dmsOutputElement: HTMLHeadingElement;
        private _decimalOutputElement: HTMLHeadingElement;
        private _coordinateConverter: Geo.CoordinateConverter.Interfaces.ICoordinateConverter;
        private _model: Geo.CoordinateConverter.Interfaces.ICoordinateDms;

        constructor(coordinateConverter: Geo.CoordinateConverter.Interfaces.ICoordinateConverter,
                coordinateInputElement: HTMLInputElement,
                gpsOutputElement: HTMLHeadingElement,
                dmsOutputElement: HTMLHeadingElement,
                decimalOutputElement: HTMLHeadingElement,
                onInputChanged: ()=>void
            ) {
            this._coordinateConverter = coordinateConverter;
            this._coordinateInputElement = coordinateInputElement;
            this._gpsOutputElement = gpsOutputElement;
            this._dmsOutputElement = dmsOutputElement;
            this._decimalOutputElement = decimalOutputElement;
            this._coordinateInputElement.onkeyup = onInputChanged;
        }
        public GetPosition() : void {
            navigator.geolocation.getCurrentPosition((position) => {
                this.GotPosition(new Geo.CoordinateConverter.Model.CoordinateDecimalInfo(position.coords.latitude, position.coords.longitude));
                var maxAge:Date = new Date(Date.now() - 20000);
                if (position.coords.accuracy > 50 || position.timestamp < maxAge) {
                    this.GetPositionL2();
                }
            }, (err) => {
                alert('GetPosition navigator.geolocation.getCurrentPosition ERROR ' + err.message);
            }, {maximumAge:Infinity});
        }
        public GetPositionL2() : void {
            navigator.geolocation.getCurrentPosition((position) => {
                this.GotPosition(new Geo.CoordinateConverter.Model.CoordinateDecimalInfo(position.coords.latitude, position.coords.longitude));
                var maxAge:Date= new Date(Date.now() - 10000);
                if (position.coords.accuracy > 20 || position.timestamp <maxAge) {
                    this.GetPositionL3();
                }
            }, (err) => {
                alert('GetPositionL2 navigator.geolocation.getCurrentPosition ERROR ' + err.message);
            }, {maximumAge:30000});
        }
        public GetPositionL3() : void {
            navigator.geolocation.getCurrentPosition((position) => {
                this.GotPosition(new Geo.CoordinateConverter.Model.CoordinateDecimalInfo(position.coords.latitude, position.coords.longitude));
            }, (err) => {
                alert('GetPositionL3 navigator.geolocation.getCurrentPosition ERROR ' + err.message);
            }, {enableHighAccuracy:true});
        }
        public GotPosition(position:Geo.CoordinateConverter.Interfaces.ICoordinateDecimal): void {
            var newPosition: string = position.ToString();
            if (this.CoordinateInput != newPosition){
                this.CoordinateInput = newPosition;
                this.InputChanged();
            }
        }
        public InputChanged(): void {
            try {
                this.Model = this.CoordinateConverter.ParseCoordinateDms(this.CoordinateInput);
                this.CoordinateDecimalOutput = this.Model.ToCoordinateDecimal().ToString();
                this.CoordinateGpsOutput = this.Model.ToCoordinateDm().ToString();
                this.CoordinateDmsOutput = this.Model.ToCoordinateDms().ToString();
                
                //FIX
                initialize();
            } catch (ex) {
                this.Model = null;
                this.CoordinateDecimalOutput = '';
                this.CoordinateGpsOutput = '';
                this.CoordinateDmsOutput = '';
            }
        }

        public get CoordinateConverter(): Geo.CoordinateConverter.Interfaces.ICoordinateConverter {
            return this._coordinateConverter;
        }
        public get Model(): Geo.CoordinateConverter.Interfaces.ICoordinateDms {
            return this._model;
        }
        public set Model(value:Geo.CoordinateConverter.Interfaces.ICoordinateDms) {
            this._model = value;
        }
        
        public get CoordinateInput(): string {
            return this._coordinateInputElement.value;
        }
        
        public set CoordinateInput(value:string) {
            this._coordinateInputElement.value = value;
        }

        public set CoordinateDecimalOutput(value:string) {
            this._decimalOutputElement.innerHTML = value;
        }

        public set CoordinateGpsOutput(value:string) {
             this._gpsOutputElement.innerHTML = value;
        }

        public set CoordinateDmsOutput(value:string) {
             this._dmsOutputElement.innerHTML = value;
        }
    }
}

var ViewModel : Geo.CoordinateConverter.CoordinateConverterViewModel;
$(function () {
    if ((navigator && navigator.onLine) || (!navigator && window.navigator.onLine)){
        $('#lblStatus').text('Online');
    } else {
        $('#lblStatus').text('Offline');
    }

    ViewModel = new Geo.CoordinateConverter.CoordinateConverterViewModel(new Geo.CoordinateConverter.Providers.DecimalAndDmsConverter(),
        <HTMLInputElement>document.getElementById('txtCoordinates'),
        <HTMLHeadingElement>document.getElementById('lblGps'),
        <HTMLHeadingElement>document.getElementById('lblDms'),
        <HTMLHeadingElement>document.getElementById('lblDecimalDegrees'),
        () => ViewModel.InputChanged());

    ViewModel.GetPosition();
});

var map: google.maps.Map;
function initialize() {
    var mapCanvas = document.getElementById('map-canvas');
    var mapContainer = document.getElementById('map-container');

    if (((navigator && navigator.onLine) || (!navigator && window.navigator.onLine)) && google){
        var coordinateDecimal: Geo.CoordinateConverter.Interfaces.ICoordinateDecimal = ViewModel.Model.ToCoordinateDecimal();
        if (zooming){
            map.setCenter(new google.maps.LatLng(coordinateDecimal.Latitude, coordinateDecimal.Longitude));
            return;
        }
        var mapOptions = {
            zoom: 1,
            center: new google.maps.LatLng(coordinateDecimal.Latitude, coordinateDecimal.Longitude),
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map(mapCanvas, mapOptions);
        mapContainer.style.display='inline-block';

        zoomIn(mapOptions.zoom);
    }
}

//FIX Multi thread issue

var zooming = false;
function zoomIn(num) {
    var latLong: Geo.CoordinateConverter.Interfaces.ICoordinateDecimal  = ViewModel.Model.ToCoordinateDecimal();
    var to = setTimeout(function () {
        var newZoom = num + 1;
        map.setCenter(new google.maps.LatLng(latLong.Latitude, latLong.Longitude));
        map.setZoom(newZoom);
        if (newZoom < 21){
            zooming = true;
            zoomIn(newZoom);
        }else{
            zooming = false;
            map.setMapTypeId(google.maps.MapTypeId.HYBRID);
        }
    }, 1000);
}

